package cn.cdeden.knowledge.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.StringUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.oss.enumd.OssBucketOneEnum;
import cn.cdeden.common.oss.enumd.OssModuleType;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.EnterpriseMaterialFilesTree;
import cn.cdeden.knowledge.service.EnterpriseMaterialFilesTreeService;
import cn.cdeden.knowledge.service.dto.EnterpriseMaterialFilesTreeDto;
import cn.cdeden.knowledge.service.dto.EnterpriseMaterialFilesTreeQueryParam;
import cn.cdeden.knowledge.service.mapper.EnterpriseMaterialFilesTreeMapper;
import cn.cdeden.knowledge.utils.FileUtil;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.resource.api.RemoteFileService;
import cn.cdeden.resource.api.domain.RemoteFile;
import cn.cdeden.resource.api.domain.RemoteFileDto;
import cn.cdeden.system.api.RemoteDeptService;
import cn.cdeden.system.api.RemoteDictService;
import cn.cdeden.system.api.domain.vo.RemoteDeptVo;
import cn.cdeden.system.api.model.LoginUser;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author GW
* @date 2024-02-21
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = EnterpriseMaterialFilesTreeService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class EnterpriseMaterialFilesTreeServiceImpl extends ServiceImpl<EnterpriseMaterialFilesTreeMapper, EnterpriseMaterialFilesTree> implements EnterpriseMaterialFilesTreeService {

    // private final RedisUtils redisUtils;
    private final EnterpriseMaterialFilesTreeMapper enterpriseMaterialFilesTreeMapper;

    @DubboReference(check = false)
    private final RemoteFileService remoteFileService;

    @DubboReference(check = false)
    private final RemoteDeptService deptService;

    @DubboReference(check = false)
    private final RemoteDictService deptDictService;
    @Override
    public TableDataInfo<EnterpriseMaterialFilesTreeDto> queryAll(EnterpriseMaterialFilesTreeQueryParam query, Pageable pageable) {
        IPage<EnterpriseMaterialFilesTree> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<EnterpriseMaterialFilesTree> page = enterpriseMaterialFilesTreeMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        TableDataInfo<EnterpriseMaterialFilesTree> build = TableDataInfo.build(page);
        return MapstructUtils.convertTableDataInfo(build, EnterpriseMaterialFilesTreeDto.class);
    }

    @Override
    public List<EnterpriseMaterialFilesTreeDto> queryAll(EnterpriseMaterialFilesTreeQueryParam query){
        return MapstructUtils.convert(enterpriseMaterialFilesTreeMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), EnterpriseMaterialFilesTreeDto.class);
    }

    @Override
    public EnterpriseMaterialFilesTree getById(Long id) {
        return enterpriseMaterialFilesTreeMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public EnterpriseMaterialFilesTreeDto findById(Long id) {
        return MapstructUtils.convert(getById(id), EnterpriseMaterialFilesTreeDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insert(EnterpriseMaterialFilesTreeDto resources) {
        EnterpriseMaterialFilesTreeDto enterpriseMaterialFilesTreeDto = uploadEnterpriseMaterialFiles(resources.getImg(), resources.getFile(), resources.getRealName(), resources.getParentId(),resources.getDeptId());
        return enterpriseMaterialFilesTreeDto!=null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(EnterpriseMaterialFilesTreeDto resources){
        EnterpriseMaterialFilesTree entity = MapstructUtils.convert(resources, EnterpriseMaterialFilesTree.class);
        boolean ret = this.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(Set<Long> ids){
        // delCaches(ids);
        if (ids!=null&&ids.size()>0){
            for (Long id : ids) {
                EnterpriseMaterialFilesTree byId = getById(id);
                ArrayList<Long> longs = new ArrayList<>();
                longs.add(Long.valueOf(byId.getFileStorageId()));
                if (byId!=null) remoteFileService.deleteWithValidByIds(longs, false);
            }
        }
        return this.removeByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id){
        Set<Long> set = new HashSet<>(1);
        set.add(id);
        return this.deleteByIds(set);
    }

    /*
    private void delCaches(Long id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Long> ids) {
        for (Long id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<EnterpriseMaterialFilesTreeDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (EnterpriseMaterialFilesTreeDto enterpriseMaterialFilesTree : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("父亲编号", enterpriseMaterialFilesTree.getParentId());
              map.put("后缀名", enterpriseMaterialFilesTree.getSuffix());
              map.put("名称", enterpriseMaterialFilesTree.getRealName());
              map.put("类型", enterpriseMaterialFilesTree.getType());
              map.put("储存表id", enterpriseMaterialFilesTree.getFileStorageId());
              map.put("储存服务器类型", enterpriseMaterialFilesTree.getStorageType());
              map.put("文件大小", enterpriseMaterialFilesTree.getFileSize());
              map.put("创建编号", enterpriseMaterialFilesTree.getCreateId());
              map.put("创建者", enterpriseMaterialFilesTree.getCreateBy());
              map.put("创建者", enterpriseMaterialFilesTree.getCreateBy());
              map.put("创建日期", enterpriseMaterialFilesTree.getCreateTime());
              map.put("更新编号", enterpriseMaterialFilesTree.getUpdateId());
              map.put("更新者", enterpriseMaterialFilesTree.getUpdateBy());
              map.put("更新时间", enterpriseMaterialFilesTree.getUpdateTime());
              map.put("删除编号", enterpriseMaterialFilesTree.getDeleteId());
              map.put("删除者", enterpriseMaterialFilesTree.getDeleteBy());
              map.put("删除时间", enterpriseMaterialFilesTree.getDeleteTime());
                map.put(" deleteType",  enterpriseMaterialFilesTree.getDeleteType());
                map.put(" imgSize",  enterpriseMaterialFilesTree.getImgSize());
              map.put("图片存储id", enterpriseMaterialFilesTree.getImgStorageId());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/

    /**
     * 上传企业资源
     */
    @Override
    public EnterpriseMaterialFilesTreeDto uploadEnterpriseMaterialFiles(MultipartFile image, MultipartFile file, String realName, String parentId,Long deptId){
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (file == null || file.isEmpty())throw new RuntimeException("file cannot be null");
        if (StringUtils.isNullOrBlank(realName))throw new RuntimeException("realName cannot be null");
        if (StringUtils.isNullOrBlank( parentId ))throw new RuntimeException("parentId cannot be null");
        RemoteFile newRemoteFile = new RemoteFile();
        if (image==null||image.isEmpty()){

//            storage = fileStorageUtils.create(user.getId().toString(), user.getUsername(),StorageFolderTypeEnum.ENTERPRISE_MATERIAL.getCode(),file, FileEnums.ENTERPRISE_MATERIAL,null);
            RemoteFileDto remoteFile = new RemoteFileDto();
            try {
                remoteFile.setFile(file.getBytes());
            }catch (IOException e) {
                throw new RuntimeException(e);
            }
            remoteFile.setOriginalFilename(file.getOriginalFilename());
            remoteFile.setModuleType(OssModuleType.Material);
            remoteFile.setContentType(file.getContentType());
            remoteFile.setBucketName(OssBucketOneEnum.Material.getCode());
            newRemoteFile = remoteFileService.upload(remoteFile);
        }else {
            RemoteFileDto remoteFile = new RemoteFileDto();
            try {
                remoteFile.setFile(file.getBytes());
                remoteFile.setCoverFile(image.getBytes());
            }catch (IOException e) {
                throw new RuntimeException(e);
            }
            remoteFile.setOriginalFilename(file.getOriginalFilename());
            remoteFile.setModuleType(OssModuleType.Material);
            remoteFile.setContentType(file.getContentType());
            remoteFile.setBucketName(OssBucketOneEnum.Material.getCode());
            remoteFile.setCoverSuffix(FileUtil.getSuffix(image.getOriginalFilename()));
            remoteFile.setCoverContentType(image.getContentType());
            newRemoteFile = remoteFileService.upload(remoteFile);
        }
        //校验命名
        List<EnterpriseMaterialFilesTree> list = enterpriseMaterialFilesTreeMapper.lambdaQuery().eq(EnterpriseMaterialFilesTree::getRealName,realName).eq(EnterpriseMaterialFilesTree::getParentId, parentId).eq(EnterpriseMaterialFilesTree::getDeptId, loginUser.getDeptId()).list();
        if (list.size()>0)throw new RuntimeException("分类下资源命名重复");
        //存储文件以及数据
        EnterpriseMaterialFilesTree enterpriseMaterialFilesTree = new EnterpriseMaterialFilesTree();
        enterpriseMaterialFilesTree.setFileSize(newRemoteFile.getFileSize());
        enterpriseMaterialFilesTree.setFileStorageId(newRemoteFile.getOssId().toString());
//        enterpriseMaterialFilesTree.setImgSize(imageStorage.getSize());
//        enterpriseMaterialFilesTree.setImgStorageId(imageStorage.getStorageId().toString());
        enterpriseMaterialFilesTree.setRealName(realName);
        enterpriseMaterialFilesTree.setType(FileUtil.getDocumentType(newRemoteFile.getFileSuffix())==null?"其他":FileUtil.getDocumentType(newRemoteFile.getFileSuffix()));
        enterpriseMaterialFilesTree.setSuffix(newRemoteFile.getFileSuffix());
        enterpriseMaterialFilesTree.setParentId(parentId);
        enterpriseMaterialFilesTree.setStorageType("minio");
        enterpriseMaterialFilesTree.setDeptId(deptId);
        save(enterpriseMaterialFilesTree);
        return MapstructUtils.convert(enterpriseMaterialFilesTree,EnterpriseMaterialFilesTreeDto.class);
    }
    @Override
    public TableDataInfo<EnterpriseMaterialFilesTreeDto> getMaterialsFilePage(EnterpriseMaterialFilesTreeQueryParam param, Pageable pageable){
//        FileUserDto user = FileUserUtils.getUser();
        LoginUser loginUser = LoginHelper.getLoginUser();
        IPage<EnterpriseMaterialFilesTree> queryPage = PageUtil.toMybatisPage(pageable);
        RemoteDeptVo byId = deptService.getById(loginUser.getDeptId());
        ArrayList<RemoteDeptVo> depts = new ArrayList<>();
        List<RemoteDeptVo> superiors = deptService.getSuperiorAll(byId.getDeptId());
        List<Long> collect = superiors.stream().map(RemoteDeptVo::getDeptId).collect(Collectors.toList());
//        param.setDeptId(collect);
        QueryWrapper<EnterpriseMaterialFilesTree> predicate = QueryHelpMybatisPlus.getPredicate(param);

        predicate.lambda().and(consumer -> {
            consumer.in(EnterpriseMaterialFilesTree::getDeptId,collect).or().isNull(EnterpriseMaterialFilesTree::getDeptId);
                }
        );
        IPage<EnterpriseMaterialFilesTree> page = enterpriseMaterialFilesTreeMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(param));
        TableDataInfo<EnterpriseMaterialFilesTree> build = TableDataInfo.build(page);
        return MapstructUtils.convertTableDataInfo(build,EnterpriseMaterialFilesTreeDto.class);
    }
}
